/*******************************************************************************
 * Copyright (c) 2014 IBM Corp.
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * and Eclipse Distribution License v1.0 which accompany this distribution.
 *
 * The Eclipse Public License is available at
 *    http://www.eclipse.org/legal/epl-v10.html
 * and the Eclipse Distribution License is available at
 *   http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * Contributors:
 *    Ian Craggs - initial API and implementation and/or initial documentation
 *    Sergio R. Caprile - clarifications and/or documentation extension
 *******************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "cmsis_os2.h"
#include "ohos_init.h"

#include "MQTTClient.h"
#include "wifi_sta_connect.h"

#include "cJSON.h"



static unsigned char sendBuf[1000];
static unsigned char readBuf[1000];

#define WIFI_SSID "MY_SW"
#define WIFI_PWD "12345678"

#define HOST_ADDR "117.78.16.25"

#define Device_Id "1234swswsw"

#define PUBLISH_TOPIC "$oc/devices/"Device_Id"/sys/properties/report"
#define SUBCRIB_TOPIC "$oc/devices/"Device_Id"/sys/commands/+" ///request_id={request_id}"
#define RESPONSE_TOPIC "$oc/devices/"Device_Id"/sys/commands/response" ///request_id={request_id}"


Network network;
MQTTClient client;


void messageArrived(MessageData* data)
{
    int rc;
    printf("Message arrived on topic %.*s: %.*s\n", data->topicName->lenstring.len, data->topicName->lenstring.data,
           data->message->payloadlen, data->message->payload);

   //get request id
    char *request_id_idx=NULL;
    char request_id[20]={0};
    request_id_idx = strstr(data->topicName->lenstring.data,"request_id=");
    strncpy(request_id,request_id_idx+11,19);
    printf("request_id = %s\n",request_id);

    //create response topic
    char rsptopic[128]={0};
    sprintf(rsptopic,"%s/request_id=%s",RESPONSE_TOPIC,request_id);
    printf("rsptopic = %s\n",rsptopic);

    //response message
    MQTTMessage message;
    char payload[300];
    message.qos = 0;
    message.retained = 0;
    message.payload = payload;
    sprintf(payload, "{ \
    \"result_code\": 0, \
    \"response_name\": \"COMMAND_RESPONSE\", \
    \"paras\": { \
        \"result\": \"success\" \
    } \
    }" );
    message.payloadlen = strlen(payload);

    //publish the msg to responese topic
    if ((rc = MQTTPublish(&client, rsptopic, &message)) != 0) {
        printf("Return code from MQTT publish is %d\n", rc);
        NetworkDisconnect(&network);
        MQTTDisconnect(&client);
        
    }
    /*{"command_name":"motor","paras":{"speed":"1","onoff":"ON"},"service_id":"fanserver"}*/
    cJSON *root = cJSON_ParseWithLength( data->message->payload, data->message->payloadlen);
    if(root != NULL){
        cJSON *cmd_name = cJSON_GetObjectItem(root,"command_name");
        if(cmd_name != NULL){
            char *cmd_name_str = cJSON_GetStringValue(cmd_name);

            if(strcmp(cmd_name_str,"motor") == 0){
                 cJSON *para_obj = cJSON_GetObjectItem(root,"paras");
                 int speed;
                 if(para_obj){
                    cJSON *level_obj = cJSON_GetObjectItem(para_obj,"speed");
                    if(level_obj != NULL){
                        speed = atoi(cJSON_GetStringValue(level_obj));
                        printf("motor speed = %d\n",speed);
                    }
                    cJSON *onoff_obj = cJSON_GetObjectItem(para_obj,"onoff");
                     if(onoff_obj != NULL){
                        char *onoff=cJSON_GetStringValue(onoff_obj);
                        printf("motor onoff is %s\n",onoff);

                        if(strcmp(onoff,"ON") == 0){
                            //启动马达
                            motor_speed(speed);
                        }else{
                            //关闭马达
                            motor_speed(0);
                        }
                        
                    }
                 }
            }else if(strcmp(cmd_name_str,"led_cmd") == 0){
                cJSON *para_obj = cJSON_GetObjectItem(root,"paras");
                cJSON *status_obj = cJSON_GetObjectItem(para_obj,"led_onoff");
                    // if(status_obj != NULL){
                    char *onoff=cJSON_GetStringValue(status_obj);
                    printf("led onoff is %s\n",onoff);
                    int led_onoff_val = 0;
                    if(strcmp(onoff,"ON")==0){
                        led_onoff_val = 1;
                    }else {
                        led_onoff_val = 0;
                    }

                    light_onoff(led_onoff_val);
                    
                
            }else if(strcmp(cmd_name_str,"led_brightness") == 0){
                cJSON *para_obj = cJSON_GetObjectItem(root,"paras");
                cJSON *brightness_obj = cJSON_GetObjectItem(para_obj,"brightness");
                    
                    int percent=(int)cJSON_GetNumberValue(brightness_obj);
                    printf("led brightness percent %d\n",percent);
                    light_brightness( percent);
                }
            }

        }

        cJSON_Delete(root);

   
}

static void MQTTDemoTask(void)
{

    printf(">> MQTTDemoTask ...\n");
    /*连接wifi*/
    WifiConnect(WIFI_SSID, WIFI_PWD);
    printf("Starting ...\n");
    int rc, count = 0;

    /*网络初始化*/
    NetworkInit(&network);
    printf("NetworkConnect  ...\n");

    motor_init();
    light_init();
begin:
    /* 连接网络*/
    NetworkConnect(&network, HOST_ADDR, 1883);
    printf("MQTTClientInit  ...\n");
    /*MQTT客户端初始化*/
    MQTTClientInit(&client, &network, 2000, sendBuf, sizeof(sendBuf), readBuf, sizeof(readBuf));

    MQTTString clientId = MQTTString_initializer;
    clientId.cstring = Device_Id;

    MQTTString userName = MQTTString_initializer;
    userName.cstring = Device_Id;

    MQTTString password = MQTTString_initializer;
    password.cstring = "12345678";

    MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
    data.clientID = clientId;

    data.username = userName;
	data.password = password;

    data.willFlag = 0;
    data.MQTTVersion = 4;
    data.keepAliveInterval = 60;
    data.cleansession = 1;

    printf("MQTTConnect  ...\n");
    rc = MQTTConnect(&client, &data);
    if (rc != 0) {
        printf("MQTTConnect: %d\n", rc);
        NetworkDisconnect(&network);
        MQTTDisconnect(&client);
        osDelay(200);
        goto begin;
    }

    // printf("MQTTSubscribe  ...\n");
    rc = MQTTSubscribe(&client, SUBCRIB_TOPIC, 0, messageArrived);

    if (rc != 0) {
        printf("MQTTSubscribe: %d\n", rc);
        osDelay(200);
        goto begin;
    }

    while (++count) {
        float temp;
        float humi;

        // SHT3X_ReadMeasurementBuffer(&temp,&humi);

        MQTTMessage message;
        char *publishtopic=PUBLISH_TOPIC;

        char payload[300]={0};

        cJSON *root = cJSON_CreateObject();

        extern float g_temp;
        extern float g_humi;

        if(root != NULL){

            cJSON *serv_arr = cJSON_AddArrayToObject(root, "services");

            cJSON *arr_item =  cJSON_CreateObject();

            cJSON_AddStringToObject(arr_item,"service_id","fanserver");

            cJSON *pro_obj = cJSON_CreateObject();
            cJSON_AddItemToObject(arr_item,"properties",pro_obj);

            cJSON_AddStringToObject(pro_obj,"fan_state","ON");
            cJSON_AddNumberToObject(pro_obj,"humi",g_humi);
            cJSON_AddNumberToObject(pro_obj,"temp",g_temp);

            cJSON_AddItemToArray(serv_arr,arr_item);

            char *palyload_str = cJSON_PrintUnformatted(root);

            strcpy(payload,palyload_str);

            cJSON_free(palyload_str);
            cJSON_Delete(root);

        }
     
        message.qos = 0;
        message.retained = 0;
        message.payload = payload;
        // sprintf(payload, "{\"services\": [  \
        //     {\"service_id\": \"fan_serv\",  \"properties\": {\"temprature\": %02f,\"humidity\": %02f } \
        //     }   \
        //     ]}", g_temp,g_humi);
        message.payloadlen = strlen(payload);

        if ((rc = MQTTPublish(&client, publishtopic, &message)) != 0) {
            printf("Return code from MQTT publish is %d\n", rc);
            NetworkDisconnect(&network);
            MQTTDisconnect(&client);
            goto begin;
        }else{
            printf("mqtt publish success:%s\n",payload);
        }
        /*阻塞至多5000ms,有消息下发则退出阻塞*/
        MQTTYield(&client, 5000);
        // osDelay(500);
    }
}    

static void MQTTDemo(void)
{
    osThreadAttr_t attr;

    attr.name = "MQTTDemoTask";
    attr.attr_bits = 0U;
    attr.cb_mem = NULL;
    attr.cb_size = 0U;
    attr.stack_mem = NULL;
    attr.stack_size = 10240;
    attr.priority = osPriorityNormal;

    if (osThreadNew((osThreadFunc_t)MQTTDemoTask, NULL, &attr) == NULL) {
        printf("[MQTT_Demo] Failed to create MQTTDemoTask!\n");
    }
}

APP_FEATURE_INIT(MQTTDemo);